package kaoqin

import (
	"image"
	"image/color"
	"image/draw"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"github.com/disintegration/imaging"
	"github.com/golang/freetype"
	"github.com/golang/freetype/truetype"
	"gocv.io/x/gocv"
)

var (
	ImagePath = "D:/Myprog/Android/Image"
	DataPath  = "D:/Myprog/Panda/src"
)

const (
	fontPath = "C:/Windows/Fonts/simkai.ttf"
	fontSize = 30.0
)

// var logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)

// MatchTemplate 函数用于在给定的屏幕截图（screenName）中查找与模板图像（tempName）匹配的位置，并返回匹配区域的中心坐标。
//
// 参数：
//
//	screenName string: 屏幕截图的文件名。
//	tempName string: 模板图像的文件名。
//
// 返回值：
//
//	centerX, centerY int: 匹配区域的中心坐标。
func MatchTemplate(screenName, tempName string) (centerX, centerY int) {
	// 读取原图和按钮模板
	imgScene := gocv.IMRead(screenName, gocv.IMReadColor)
	defer imgScene.Close()
	imgTemplate := gocv.IMRead(tempName, gocv.IMReadColor)
	defer imgTemplate.Close()
	// 执行模板匹配
	result := gocv.NewMat()
	defer result.Close()
	gocv.MatchTemplate(imgScene, imgTemplate, &result, gocv.TmCcoeffNormed, gocv.NewMat())
	// 获取最佳匹配位置
	_, maxVal, _, maxLoc := gocv.MinMaxLoc(result)
	if maxVal < 0.9 { // 置信度阈值
		log.Fatal("未找到匹配按钮")
	}
	log.Printf("匹配位置: %v", maxLoc)
	// 绘制匹配区域矩形
	rect := image.Rect(maxLoc.X, maxLoc.Y,
		maxLoc.X+imgTemplate.Cols(),
		maxLoc.Y+imgTemplate.Rows())
	gocv.Rectangle(&imgScene, rect, color.RGBA{0, 255, 0, 0}, 3)
	// 计算中心位置
	centerX = maxLoc.X + (imgTemplate.Cols() / 2)
	centerY = maxLoc.Y + (imgTemplate.Rows() / 2)
	// 标记中心点
	gocv.Circle(&imgScene, image.Pt(centerX, centerY), 5, color.RGBA{255, 0, 0, 0}, -1)
	// 保存结果
	gocv.IMWrite("result.jpg", imgScene)
	// 打印中心坐标
	log.Printf("中心位置: (%d,%d)", centerX, centerY)
	time.Sleep(10 * time.Second)
	return centerX, centerY
}

// Mark 函数用于在图像上添加标记并保存处理后的图像
//
// 参数:
//
//	imgName string: 需要处理的图像文件名
//	saveName string: 处理后保存的图像文件名
//
// 返回值:
//
//	error: 处理过程中可能出现的错误
func Mark(imgName, saveName string) error {
	// 打开基础图像
	img, err := imaging.Open(filepath.Join(ImagePath, imgName))
	if err != nil {
		return err
	}
	// 创建绘图上下文
	context := freetype.NewContext()
	font, _ := loadFont()
	context.SetFont(font)
	context.SetFontSize(fontSize)
	context.SetClip(img.Bounds())
	// 将img转换为*image.NRGBA类型
	newimg := imaging.Clone(img)
	context.SetDst(newimg)
	context.SetSrc(image.NewUniform(color.RGBA{0, 255, 0, 255})) //设置字体颜色
	// 绘制网格线
	drawGrid(newimg, context)
	// 保存处理后的图像
	log.Printf("绘制网格线和文字完成")
	return imaging.Save(newimg, filepath.Join(ImagePath, saveName))
}

// loadFont 函数用于加载指定路径的字体文件，并返回一个字体对象和一个错误值
// 如果加载字体文件失败，则返回nil和错误值
// 参数：
//
//	无
//
// 返回值：
//
//	*truetype.Font: 加载的字体对象指针
//	error: 加载字体时可能出现的错误
func loadFont() (*truetype.Font, error) {
	fontBytes, err := os.ReadFile(fontPath)
	if err != nil {
		return nil, err
	}
	return freetype.ParseFont(fontBytes)
}

// drawLine 在图像上绘制一条从点(x1, y1)到点(x2, y2)的直线，颜色为col
// 如果(x1, y1)和(x2, y2)不在同一水平或垂直线上，则函数会抛出panic
//
// 参数:
//
//	img - 要绘制的图像对象
//	x1, y1 - 起点坐标
//	x2, y2 - 终点坐标
//	col - 线条颜色
func drawLine(img draw.Image, x1, y1, x2, y2 int, col color.Color) {
	if x1 == x2 {
		for y := 0; y1 <= y && y <= y2; y++ {
			img.Set(x1, y, col)
		}
	} else if y1 == y2 {
		for x := 0; x1 <= x && x <= x2; x++ {
			img.Set(x, y1, col)
		}
	} else {
		log.Printf("暂不支持斜线绘制,请保持(x1,y1)与(x2,y2)在同一水平或垂直线上")
	}
}

// drawGrid 在给定的图像上绘制一个网格，并在网格线上添加标注。
// 参数：
//
//	img draw.Image: 需要绘制网格的图像对象。
//	c *freetype.Context: 用于绘制文本的上下文对象。
func drawGrid(img draw.Image, c *freetype.Context) {
	bounds := img.Bounds()
	xMax := bounds.Max.X
	yMax := bounds.Max.Y
	// 绘制垂直线
	for i := 0; i <= xMax/100; i++ {
		x := i * 100
		drawLine(img, x, 0, x, yMax, color.RGBA{0, 125, 0, 75})
		// 添加文字标注
		pt1 := freetype.Pt(x-20, 25)
		pt2 := freetype.Pt(x-20, 1210)
		c.DrawString(strconv.Itoa(x), pt1)
		c.DrawString(strconv.Itoa(x), pt2)
	}
	// 绘制水平线
	for i := 0; i <= yMax/100; i++ {
		y := i * 100
		drawLine(img, 0, y, xMax, y, color.RGBA{0, 0, 125, 125})
		// 添加文字标注（可选）
		pt := freetype.Pt(5, y+10)
		c.DrawString(strconv.Itoa(y), pt)
	}
}
